/*++

Copyright (C) Microsoft Corporation, 2004

Module Name:

    fis.h

Abstract:



Notes:

Revision History:

		Nathan Obr (natobr),  February 2005
--*/

#if _MSC_VER >= 1200
#pragma warning(push)
#endif

#pragma warning(disable:4214) // bit field types other than int

/* BIDIRECTIONAL FIS */

//DMA Setup - Device to Host or Host to Device (Bidirectional) as defined in SerialATA 1.0a section 8.5.6
//The DMA Setup - Device to Host or Host to Device FIS is the mechanism by which first-party DMA access to host memory is initiated. This FIS is used to request the host or device to program its DMA controller before transferring data. The FIS allows the actual host memory regions to be abstracted (depending on implementation) by having memory regions referenced via a base memory descriptor representing a memory region that the host has granted the device access to. The specific implementation for the memory descriptor abstraction is not defined. The device or host is informed of the 64-bit DMA buffer identifier/descriptor at some previous time by an implementation specific mechanism such as a command issued to or as defined in a specification. Random access within a buffer is accomplished by using the buffer offset. First party DMA is a superset capability not necessarily supported by legacy devices or legacy device drivers but essential for accommodating future capabilities.
typedef struct _AHCI_DMA_SETUP_FIS {

	UCHAR FisType;	//0x41
	UCHAR Reserved1 :5;
	UCHAR D :1;		//1 is transmitter to receiver
	UCHAR I :1;
	UCHAR Reserved2 :1;	
	UCHAR Reserved3[2];
	
	ULONG DmaBufferIdentifierLow;
	ULONG DmaBufferIdentifierHigh;
	ULONG Reserved4;
	ULONG DmaBufferOffset;   //Bits <1:0> must be zero
	ULONG DmaTransferCount;
	ULONG Reserved5;

}  AHCI_DMA_SETUP_FIS, *PAHCI_DMA_SETUP_FIS;

//BIST Activate - Host to Device or Device to Host (Bidirectional) as defined in SerialATA 1.0a section 8.5.7
//The BIST Activate FIS shall be used to place the receiver in one of 'n' loopback modes.
typedef struct _AHCI_BIST_ACTIVATE_FIS {

	UCHAR FisType;	// 0x58
	UCHAR Reserved1;
	UCHAR V	:1;
	UCHAR Reserved2	:1;
	UCHAR P	:1;
	UCHAR F	:1;
	UCHAR L	:1;
	UCHAR S	:1;
	UCHAR A	:1;
	UCHAR T	:1;
	UCHAR Reserved3;

	UCHAR Data[8];
} AHCI_BIST_ACTIVATE_FIS, *PAHCI_BIST_ACTIVATE_FIS;

//Data - Host to Device or Device to Host (Bidirectional) as defined in SerialATA 1.0a section 8.5.9
//The Data - Host to Device and the Data - Device to Host FIS's are used for transporting payload data, such as the data read from or written to a number of sectors on a hard drive. The FIS may either be generated by the device to transmit data to the host or may be generated by the host to transmit data to the device. This FIS is generally only one element of a sequence of transactions leading up to a data transmission and the transactions leading up to and following the Data FIS establish the proper context for both the host and device. The byte count of the payload is not an explicit parameter, rather it is inferred by counting the number of Dwords between the SOF and EOF primitives, and discounting the FIS type and CRC Dwords. The payload size shall be no more than 2048 Dwords (8192 bytes) for native implementations. Parallel ATA to Serial ATA bridge implementations should not transmit more than 2048 Dwords (8192 bytes) in any one Data FIS. However, separate bridge hardware is not required to break up PIO or DMA transfers from parallel ATA into more than one Serial ATA Data FIS and may therefore produce payloads longer than 2048 Dwords. Receivers shall tolerate reception of data payloads longer than 2048 Dwords without error. Non-packet devices, with or without bridges, should report a SET MULTIPLE limit of 16 sectors or less in word 47 of their IDENTIFY DEVICE information. In the case that the transfer length represents an odd number of words, the last word shall be placed in the low order (word 0) of the final Dword and the high order word (word 1) of the final Dword shall be padded with zeros before transmission.
typedef struct _AHCI_DATA_FIS {

	UCHAR FisType;		//0x46
	UCHAR Reserved1[3];

	ULONG Data[2048];  //TODO: should this be a pointer to a buffer? How would that even work?

}  AHCI_DATA_FIS, *PAHCI_DATA_FIS;

/* DEVICE TO HOST FIS */

//PIO Setup - Device to Host as defined in SerialATA 1.0a section 8.5.8
//The PIO Setup - Device to Host FIS is used by the device to provide the host adapter with sufficient information regarding a PIO data phase to allow the host adapter to efficiently handle PIO data transfers. For PIO data transfers, the device shall send to the host a PIO Setup - Device to Host FIS just before each and every data transfer FIS that is required to complete the data transfer. Data transfers from Host to Device as well as data transfers from Device to Host shall follow this algorithm. Because of the stringent timing constraints in the ATA standard, the PIO Setup FIS includes both the starting and ending status values. These are used by the host adapter to first signal to host software readiness for PIO write data (BSY deasserted and DRQ asserted), and following the PIO write burst to properly signal host software by deasserting DRQ and possibly raising BSY.
typedef struct _AHCI_PIO_SETUP_FIS {

	UCHAR FisType;		//0x5F
	UCHAR Reserved1 :5;
	UCHAR D :1;			// 1 is write (device to host)
	UCHAR I :1;
	UCHAR Reserved2 :1;
	UCHAR Status;
	UCHAR Error;
	
	UCHAR SectorNumber;
	UCHAR CylLow;
	UCHAR CylHigh;
	UCHAR Dev_Head;
	
	UCHAR SectorNumb_Exp;
	UCHAR CylLow_Exp;
	UCHAR CylHigh_Exp;
	UCHAR Reserved3;
	
	UCHAR SectorCount;
	UCHAR SectorCount_Exp;
	UCHAR Reserved4;
	UCHAR E_Status;
	
	USHORT TransferCount;
 	UCHAR Reserved5[2];

}  AHCI_PIO_SETUP_FIS, *PAHCI_PIO_SETUP_FIS;

//Register - Device to Host as defined in SerialATA 1.0a section 8.5.3
//The Register - Device to Host FIS is used to by the device to update the contents of the host adapter's Shadow Register Block. This is the mechanism by which devices indicate command completion status or otherwise change the contents of the host adapter's Shadow Register Block.
typedef struct _AHCI_D2H_REGISTER_FIS {
	UCHAR FisType;	// 0x34
	UCHAR Reserved1 :6;
	UCHAR I:1;
	UCHAR Reserved2 :1;
	UCHAR Status;
	UCHAR Error;

	UCHAR SectorNumber;
	UCHAR CylLow;
	UCHAR CylHigh;
	UCHAR Dev_Head;

	UCHAR SectorNum_Exp;
	UCHAR CylLow_Exp;
	UCHAR CylHigh_Exp;
	UCHAR Reserved;

	UCHAR SectorCount;
	UCHAR SectorCount_Exp;
	UCHAR Reserved3[2];

	UCHAR Reserved4[4];
} AHCI_D2H_REGISTER_FIS, *PAHCI_D2H_REGISTER_FIS;

//Set Device Bits - Device to Host as defined in SerialATA 1.0a section 8.5.4
//The Set Device Bits - Device to Host FIS is used by the device to load Shadow Register Block bits for which the device has exclusive write access. These bits are the eight bits of the Error register and six of the eight bits of the Status register. This FIS does not alter bit 7, BSY, or bit 3, DRQ, of the Status register. The FIS includes a bit to signal the host adapter to generate an interrupt if the BSY bit and the DRQ bit in the shadow Status Register are both cleared to zero when this FIS is received. Some Serial ATA to parallel ATA bridge solutions may elect to not support this FIS based on the requirements of their target markets. Upon reception, such devices will process this FIS as if it were an invalid FIS type and return the R_ERR end of frame handshake.
typedef struct _AHCI_SET_DEVICE_BITS_FIS {

	UCHAR FisType;	 //0xA1

    UCHAR PMPort: 4;
	UCHAR Reserved1 :2;
	UCHAR I :1;
	UCHAR N :1;

	UCHAR Status_Lo :3;
	UCHAR Reserved2 :1;
	UCHAR Status_Hi :3;
	UCHAR Reserved3 :1;

	UCHAR Error;
	
	UCHAR Reserved5[4];
}  AHCI_SET_DEVICE_BITS_FIS, *PAHCI_SET_DEVICE_BITS_FIS;
typedef struct _AHCI_UNKNOWN_FIS {
  UCHAR Raw[64];
} AHCI_UNKNOWN_FIS, *PAHCI_UNKNOWN_FIS;

//DMA Activate - Device to Host as defined in SerialATA 1.0a section 8.5.5
//The DMA Activate - Device to Host FIS is used by the device to signal the host to proceed with a DMA data transfer of data from the host to the device. This is the mechanism by which a legacy device signals its readiness to receive DMA data from the host. A situation may arise where the host needs to send multiple Data FIS's in order to complete the overall data transfer request. The host shall wait for a successful reception of a DMA Activate FIS before sending each of the Data FIS's that are needed.
typedef struct _AHCI_DMA_ACTIVATE_FIS {

	UCHAR FisType;   //0x39
	UCHAR Reserved1[3];

} _DMA_ACTIVATE_FIS, *P_DMA_ACTIVATE_FIS;

/* HOST TO DEVICE FIS */

//Register - Host to Device as defined in SerialATA 1.0a section 8.5.2
//The Register - Host to Device FIS is used to transfer the contents of the Shadow Register Block from the host to the device. This is the mechanism for issuing legacy ATA commands to the device.
//It is important to note that Serial ATA host adapters enforce the same access control to the Shadow Register Block as legacy (parallel) ATA devices enforce to the Command Block Registers. Specifically, the host is prohibited from writing the Features, Sector Count, Sector Number, Cylinder Low, Cylinder High, or Device/Head registers when either BSY or DRQ is set in the Status Register. Any write to the Command Register when BSY or DRQ is set is ignored unless the write is to issue a Device Reset command.
typedef struct _AHCI_H2D_REGISTER_FIS {
	UCHAR FisType;	// 0x27
	UCHAR Reserved1 :7;
	UCHAR C :1;		//This bit is set to one when the register transfer is due to an update of the Command register. The bit is set to zero when the register transfer is due to an update of the Device Control register.
	UCHAR Command;
	UCHAR Features;

	UCHAR SectorNumber;
	UCHAR CylLow;
	UCHAR CylHigh;
	UCHAR Dev_Head;

	UCHAR SecNum_Exp;
	UCHAR CylLow_Exp;
	UCHAR CylHigh_Exp;
	UCHAR Features_Exp;

	UCHAR SectorCount;
	UCHAR SectorCount_Exp;
	UCHAR Reserved2;
	UCHAR Control;

	ULONG Reserved3;
} AHCI_H2D_REGISTER_FIS, *PAHCI_H2D_REGISTER_FIS;

typedef struct _AHCI_READ_LOG_EXT_DATA {
	UCHAR NQ :1;
	UCHAR Reserved :2;
	UCHAR TAG :5;

	UCHAR Reserved1;
	UCHAR Status;
	UCHAR Error;
	UCHAR Sector_Number;
	UCHAR Cylinder_Low;
	UCHAR Cylinder_High;
	UCHAR Dev_Head;
	UCHAR Sector_Number_Exp;
	UCHAR Cylinder_Low_Exp;
	UCHAR Cylinder_High_Exp;
	UCHAR Reserved2;
	UCHAR Sector_Count;
	UCHAR Sector_Count_Exp;
	UCHAR Reserved3[242];
	
	UCHAR Vendor_Specific[255];
	UCHAR Data_Structure_Checksum;
} AHCI_READ_LOG_EXT_DATA, *PAHCI_READ_LOG_EXT_DATA;


#if _MSC_VER >= 1200
#pragma warning(pop)
#else
#pragma warning(default:4214)
#endif

